package windbell.domain.risk.impl;

import edu.fudan.langlab.domain.statemachine.ModelObjectLogService;
import edu.fudan.langlab.domain.task.TSKRoutineProtocal;
import edu.fudan.langlab.domain.task.impl.TSKRoutineProtocalImpl;
import edu.fudan.langlab.domain.task.impl.TSKRoutineTaskGeneratorImpl;
import edu.fudan.mylang.pf.IObjectFactory;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import windbell.domain.risk.RiskCheck;
import windbell.domain.risk.RiskCheckFromSchedule;
import windbell.domain.risk.RiskCheckGenerator;
import windbell.domain.risk.RiskCheckGeneratorStatus;
import windbell.domain.risk.RiskCheckSourceType;
import windbell.domain.risk.RiskCheckTarget;
import windbell.domain.risk.RiskCheckTemplate;
import windbell.domain.risk.impl.RiskCheckFromScheduleImpl;
import windbell.domain.risk.impl.RiskCheckTargetImpl;
import windbell.domain.risk.impl.RiskCheckTemplateImpl;
import windbell.domain.risk.proxy.RiskCheckGeneratorProxy;

@Entity
@DiscriminatorValue("RISKCHECKGENERATOR_TYPE")
public class RiskCheckGeneratorImpl extends TSKRoutineTaskGeneratorImpl implements RiskCheckGenerator {
  public RiskCheckGeneratorImpl() {
    super();
  }
  
  private RiskCheckGeneratorStatus Status;
  
  public RiskCheckGeneratorStatus getStatus() {
    return this.Status;
  }
  
  private ModelObjectLogService getModelObjectLogService() {
    return getBeanFactory().getBean(ModelObjectLogService.class);
  }
  
  private void _start() {
    
    Status=RiskCheckGeneratorStatus.created;
  }
  
  public void start() {
    if(Status==null){
    	_start();
    	getModelObjectLogService().createLog(this,"Status","Start");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskCheckGeneratorEventsManager.class).fireStarted(this);					
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException("allready started");
    }
  }
  
  private void _delete() {
    getObjectFactory().delete(this);
    
  }
  
  public void delete() {
    if(Status==RiskCheckGeneratorStatus.created){
    	_delete();
    	getModelObjectLogService().createLog(this,"Status","delete");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskCheckGeneratorEventsManager.class).fireDelete(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _addCheckTarget(final RiskCheckTarget item) {
    
    this.addtoCheckTargets(item);
  }
  
  public void addCheckTarget(final RiskCheckTarget item) {
    if(Status==RiskCheckGeneratorStatus.created){
    	_addCheckTarget(item);
    	getModelObjectLogService().createLog(this,"Status","addCheckTarget");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskCheckGeneratorEventsManager.class).fireAddCheckTarget(this,item);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _generateTask(final Date date) {
    RiskCheckFromSchedule riskCheckFromSchedule=RiskCheckFromScheduleImpl.create(this.checkTemplate,getObjectFactory());
    
    final Procedure1<RiskCheckFromSchedule> _function = new Procedure1<RiskCheckFromSchedule>() {
        public void apply(final RiskCheckFromSchedule it) {
          it.setType(RiskCheckSourceType.period);
          String _description = RiskCheckGeneratorImpl.this.getDescription();
          String _plus = (_description + " - ");
          SimpleDateFormat _simpleDateFormat = new SimpleDateFormat("yyyy\u5E74MM\u6708dd\u65E5");
          String _format = _simpleDateFormat.format(date);
          String _plus_1 = (_plus + _format);
          it.setDescription(_plus_1);
          it.setGenerator(RiskCheckGeneratorImpl.this);
          it.setDate(date);
        }
      };
    final RiskCheckFromSchedule source = ObjectExtensions.<RiskCheckFromSchedule>operator_doubleArrow(riskCheckFromSchedule, _function);
    final Procedure1<RiskCheckTarget> _function_1 = new Procedure1<RiskCheckTarget>() {
        public void apply(final RiskCheckTarget checkTarget) {
          final Procedure1<RiskCheck> _function = new Procedure1<RiskCheck>() {
              public void apply(final RiskCheck it) {
                it.setCheckTarget(checkTarget);
              }
            };
          final RiskCheck riskCheck = source.createRiskCheck(_function);
          riskCheck.publish(date);
        }
      };
    IterableExtensions.<RiskCheckTarget>forEach(this.checkTargets, _function_1);
    Status=RiskCheckGeneratorStatus.generated;
  }
  
  public void generateTask(final Date date) {
    if(Status==RiskCheckGeneratorStatus.created){
    	_generateTask(date);
    	getModelObjectLogService().createLog(this,"Status","generateTask");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskCheckGeneratorEventsManager.class).fireGenerateTask(this,date);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  public Boolean isCreated() {
    return windbell.domain.risk.RiskCheckGeneratorStatus.created==Status;
  }
  
  public Boolean isGenerated() {
    return windbell.domain.risk.RiskCheckGeneratorStatus.generated==Status;
  }
  
  @JoinColumn(name = "checkTemplate_id")
  @ManyToOne(targetEntity = RiskCheckTemplateImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RiskCheckTemplate checkTemplate;
  
  public RiskCheckTemplate getCheckTemplate() {
    return this.checkTemplate;
  }
  
  public RiskCheckGenerator setCheckTemplate(final RiskCheckTemplate checkTemplate) {
    this.checkTemplate = checkTemplate;
    return this;			
    
  }
  
  @JoinColumn(name = "protocal_id")
  @ManyToOne(targetEntity = TSKRoutineProtocalImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private TSKRoutineProtocal protocal;
  
  public TSKRoutineProtocal getProtocal() {
    return this.protocal;
  }
  
  public RiskCheckGenerator setProtocal(final TSKRoutineProtocal protocal) {
    this.protocal = protocal;
    return this;			
    
  }
  
  @ManyToMany(targetEntity = RiskCheckTargetImpl.class)
  @JoinTable(name = "m2m_riskcheckgenerator_checktargets", joinColumns = @JoinColumn(name = "riskcheckgenerator_id") , inverseJoinColumns = @JoinColumn(name = "riskCheckTarget_inv_id") )
  private Collection<RiskCheckTarget> checkTargets = new java.util.ArrayList<windbell.domain.risk.RiskCheckTarget>();;
  
  public Collection<RiskCheckTarget> getCheckTargets() {
    return this.checkTargets;
  }
  
  public RiskCheckGenerator setCheckTargets(final Iterable<RiskCheckTarget> checkTargets) {
    removeAllCheckTargets();
    for(RiskCheckTarget ca : checkTargets){
    	addtoCheckTargets(ca);
    }
    return this;		
    
  }
  
  public RiskCheckGenerator addtoCheckTargets(final RiskCheckTarget riskCheckTarget) {
    this.checkTargets.add(riskCheckTarget);
    return this;
    
  }
  
  public RiskCheckGenerator removeAllCheckTargets() {
    this.checkTargets.clear();
    return this;	
    
  }
  
  public RiskCheckGenerator removeFromCheckTargets(final RiskCheckTarget riskCheckTarget) {
    this.checkTargets.remove(riskCheckTarget);
    return this;
    
  }
  
  public String getDescription() {
    String _name = this.checkTemplate.getName();
    return _name;
  }
  
  public static RiskCheckGenerator create(final IObjectFactory objectFactory) {
    windbell.domain.risk.RiskCheckGenerator riskCheckGenerator = new windbell.domain.risk.impl.RiskCheckGeneratorImpl(
    );
    objectFactory.create(riskCheckGenerator);
    riskCheckGenerator.start();
    return riskCheckGenerator;			
    
  }
  
  public static RiskCheckGenerator createRiskCheckGeneratorImpl(final IObjectFactory objectFactory, final Procedure1<RiskCheckGenerator> init) {
    windbell.domain.risk.RiskCheckGenerator riskCheckGenerator = new windbell.domain.risk.impl.RiskCheckGeneratorImpl(
    );
    objectFactory.create(riskCheckGenerator);
    init.apply(riskCheckGenerator);
    riskCheckGenerator.start();
    return riskCheckGenerator;			
    
  }
  
  public RiskCheckGeneratorProxy toProxy() {
    windbell.domain.risk.proxy.RiskCheckGeneratorProxy proxy = new windbell.domain.risk.proxy.RiskCheckGeneratorProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    proxy.setStatus(this.getStatus().name());
    return proxy;
    
  }
}
